package com.clippick.clipboard;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;

import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.text.ClipboardManager;
import android.util.Log;
import co.kr.clippick.R;

import com.clippick.NewMainActivity;
import com.clippick.api.GetApi;
import com.clippick.api.GetDataFromApi;
import com.clippick.clipboard.CustomMultiPartEntity.ProgressListener;
import com.clippick.common.GlobalValue;
import com.clippick.common.Toasts;
import com.clippick.common.Utils;
import com.clippick.database.FeedOrderDBAdapter;
import com.clippick.database.HistoryDBAdapter;

@SuppressWarnings("deprecation")
public class PollingService extends Service {
	// common
	private Context mContext;

	public Context getServiceContext() {
		return mContext;
	}

	private ConnectivityManager cntManager;

	private NotificationManager notificationManager;
	private NotificationCompat.Builder mNotifBuilder;

	// Polling thread
	private PollingThread pollingThread;

	// ClipBoard thread
	private GetClipBoardThread startClipBoard;

	// system clipboard
	private ClipboardManager systemClipboard;

	/** local database manager */
	private HistoryDBAdapter dbManager;
	private FeedOrderDBAdapter feedOrderDbManager;

	public void onDestroy() {
		super.onDestroy();
		this.unregisterReceiver(this.screenOnOffReceiver);
		this.unregisterReceiver(this.imageTansferReceiver);
		this.unregisterReceiver(this.mNetworkStateReceiver);
		this.unregisterReceiver(this.doConnectLongPollingReceiver);
		pollingThread.cancel();

		mContext = null;
		pollingThread = null;
		systemClipboard = null;
	}

	/**
	 * Task Order : <br>
	 * 1. SQLite3 Open <br>
	 * 2. Start polling System Clipboard </br> 3. Register Screen on/off
	 * Receiver
	 * */
	public void onCreate() {
		super.onCreate();
		mContext = this;
		Log.d("service", "onCreate");

		cntManager = (ConnectivityManager) mContext
				.getSystemService(Context.CONNECTIVITY_SERVICE);

		GlobalValue.IS_UPDATING = false;

		// system clipboard
		if (systemClipboard == null)
			systemClipboard = (ClipboardManager) mContext
					.getSystemService(Context.CLIPBOARD_SERVICE);

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
			
			final android.content.ClipboardManager clipMngr = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
			clipMngr.addPrimaryClipChangedListener(new android.content.ClipboardManager.OnPrimaryClipChangedListener() {
	
				@Override
				public void onPrimaryClipChanged() {
					if (!GlobalValue.USER_ID.equals("") && !GlobalValue.IS_UPDATING) {
						ClipData clip = clipMngr.getPrimaryClip();
						ClipData.Item newItem = clip.getItemAt(0);
						String newItemText = (String) newItem.getText();
	
						/**
						 * accept all changes don't check if data is duplicated in
						 * database
						 */
						if (newItemText == null || newItemText.equals("")
								|| GlobalValue.PrevClip.equals(newItemText))
							return;
	
						try {
							if (Utils.checkNetwokState(cntManager)) {
								GlobalValue.PrevClip = newItemText;
								GetApi api = new GetApi(PollingService.this);
								api.insertNewClip(newItemText, "0");
								mUiHandler.sendEmptyMessage(0);
							}
						} catch (NullPointerException e) {
							e.printStackTrace();
						}
					}
				}
			});
		}else{
			if (startClipBoard == null) {
				startClipBoard = new GetClipBoardThread(this, mUiHandler);
			}
		}
		// open local database
		// String dbID = GlobalValue.USER_ID.replaceAll("@", "_")
		// .replaceAll(".", "_").replaceAll("-", "_");
		// if (dbManager == null) {
		// dbManager = new HistoryDBAdapter(this, dbID);
		// }
		//
		// // open order database manager
		// if (feedOrderDbManager == null) {
		// feedOrderDbManager = new FeedOrderDBAdapter(this, dbID);
		// }

		// polling with system clipboard
		//startClipBoard = new GetClipBoardThread(this, mUiHandler);

		// polling with server-side
		pollingThread = new PollingThread(this, mUiHandler);

		try {
			// check screen is on/off
			IntentFilter screenOnFilter = new IntentFilter(
					Intent.ACTION_SCREEN_ON);
			registerReceiver(screenOnOffReceiver, screenOnFilter);
			IntentFilter screenOffFilter = new IntentFilter(
					Intent.ACTION_SCREEN_OFF);
			registerReceiver(screenOnOffReceiver, screenOffFilter);

			// register receiver image file to server AsyncTask
			IntentFilter transferImageFilter = new IntentFilter();
			transferImageFilter.addAction("com.clippick.TransferImage");
			mContext.registerReceiver(imageTansferReceiver, transferImageFilter);

			// register receiver in actibity or in service
			IntentFilter networkStateFilter = new IntentFilter(
					ConnectivityManager.CONNECTIVITY_ACTION);
			registerReceiver(mNetworkStateReceiver, networkStateFilter);

			// register receiver to doConnectLongPolling
			IntentFilter longpollFilter = new IntentFilter();
			longpollFilter.addAction("com.clippick.LongPoll");
			registerReceiver(doConnectLongPollingReceiver, longpollFilter);
		} catch (IllegalArgumentException e) {

		}
	}

	public int onStartCommand(Intent intent, int flags, int startId) {
		super.onStartCommand(intent, flags, startId);
		Log.i("service", "onStartCommand");
		
		doConnectLongPolling();
		
		return START_STICKY;
	}

	// will be called when data modified
	Handler mUiHandler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.what == 0) {
				try {
					Toasts.showToast(mContext, getString(R.string.clipped));
				} catch (NullPointerException e) {

				}

			} else if (msg.what == 1) {
				Toasts.showToast(mContext, getString(R.string.network_fail));

			} else if (msg.what == 2) {
				// ClipPick Copy

			} else if (msg.what == 3) {
				Toasts.showToast(mContext, "Clip Fail");

			} else if (msg.what == 4) {
				Toasts.showToast(mContext, getString(R.string.network_fail));

			} else if (msg.what == 5) {
				// weak network service

			}
		}
	};

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	// access from GetPolling.class
	public HistoryDBAdapter getLocalDb() {
		return dbManager;
	}

	// access from GetPolling.class
	public FeedOrderDBAdapter getLocalOrderDb() {
		return feedOrderDbManager;
	}

	// access from GetPolling.class and GetClipBoard.class
	@SuppressLint("NewApi")
	public ClipboardManager getSystemClipboard() {
		return systemClipboard;
	}

	public void setNewClip(String content) {
		mContext = this;

		GlobalValue.isOnInsertSync = true;
		GlobalValue.AppClip = content;
		GlobalValue.PrevClip = content;
		GlobalValue.setAppClip(mContext, content);
		systemClipboard.setText(content);
	}

	/** transfer image file */
	private static int notiId = 0;

	class FileTask extends AsyncTask<Intent, Integer, String> {
		long totalSize;

		protected void onPreExecute() {
			notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
			mNotifBuilder = new NotificationCompat.Builder(mContext);

			mNotifBuilder.setTicker("Copying image...");
			mNotifBuilder.setSmallIcon(R.drawable.icon_sub);
			// Sets the progress indicator to a max value, the current
			// completion percentage, and "determinate" state
			mNotifBuilder.setProgress(100, 0, true);

			Intent intent = new Intent(mContext, NewMainActivity.class);
			intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
					| Intent.FLAG_ACTIVITY_CLEAR_TOP
					| Intent.FLAG_ACTIVITY_SINGLE_TOP);
			PendingIntent contentIntent = PendingIntent.getActivity(mContext,
					0, intent, 0);
			mNotifBuilder.setContentIntent(contentIntent);

			// Issues the notification
			if (notificationManager.hashCode() == notiId) {
				notiId++;
			}
			notificationManager.notify(notiId, mNotifBuilder.build());
		}

		@Override
		protected String doInBackground(Intent... params) {
			GetApi api = new GetApi(mContext);

			Uri uri = (Uri) params[0].getExtras().getParcelable(
					Intent.EXTRA_STREAM);

			try {
				Bitmap bm = Utils.readBitmap(mContext, uri);
				String filePath = Environment.getExternalStorageDirectory()
						.toString() + "/.ClipPick/";
				File dir = new File(filePath);
				if (!dir.exists())
					dir.mkdirs();
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				bm.compress(CompressFormat.JPEG, 100, bos);

				// image file binary
				byte[] fileByte = bos.toByteArray();

				try {
					HttpClient httpClient = new DefaultHttpClient();
					// HttpPost postRequest = new HttpPost(GetDataFromApi.SERVER
					// + GetDataFromApi.API_INSERT_IMAGE);
					HttpPost postRequest = new HttpPost(
							GetDataFromApi.IMAGE_SERVER
									+ GetDataFromApi.API_NODEJS_INSERT);

					Log.d("api", GetDataFromApi.IMAGE_SERVER
							+ GetDataFromApi.API_NODEJS_INSERT);

					ByteArrayBody bab = new ByteArrayBody(fileByte, "image"
							+ System.currentTimeMillis() + ".jpg");

					CustomMultiPartEntity reqEntity = new CustomMultiPartEntity(
							new ProgressListener() {
								@Override
								public void transferred(long num) {
									publishProgress((int) num);
								}
							});

					reqEntity.addPart("UserID", new StringBody(
							GlobalValue.USER_ID));
					reqEntity.addPart("device", new StringBody("Android"));
					reqEntity.addPart("REGISTRATION_KEY", new StringBody(
							GlobalValue.getUserRegistrationKey(mContext)));
					reqEntity.addPart("image", bab);
					totalSize = reqEntity.getContentLength();
					postRequest.setEntity(reqEntity);

					final HttpResponse response = httpClient
							.execute(postRequest);

					BufferedReader reader = new BufferedReader(
							new InputStreamReader(response.getEntity()
									.getContent(), "UTF-8"));

					String sResponse;
					StringBuilder s = new StringBuilder();

					while ((sResponse = reader.readLine()) != null) {
						s = s.append(sResponse);
					}

					Log.d("api", "respons=" + s.toString());

				} catch (Exception e) {
					Log.e(e.getClass().getName(), e.getMessage());
					e.printStackTrace();
				}

			} catch (Exception e) {
				e.printStackTrace();
			}

			return null;
		}

		@Override
		protected void onProgressUpdate(Integer... progress) {
			mNotifBuilder.setContentTitle("Copying image...");
			float per = ((float) progress[0] / (float) totalSize) * 100;

			mNotifBuilder.setContentText("" + Math.round(per) + "% completed");
			Log.i("progress", "progress : " + (int) totalSize + "/"
					+ (int) progress[0]);
			mNotifBuilder
					.setProgress((int) totalSize, (int) progress[0], false);
			notificationManager.notify(notiId, mNotifBuilder.build());
		}

		protected void onPostExecute(String unused) {
			mNotifBuilder.setProgress(0, 0, false);
			mNotifBuilder.setContentTitle("Image copied");
			mNotifBuilder.setContentText("Successfully copied");
			mNotifBuilder.setTicker("Successfully copied");
			mNotifBuilder.setContentText("Completed copying image");
			notificationManager.notify(notiId, mNotifBuilder.build());
			notiId++;
		}
	}

	BroadcastReceiver imageTansferReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			new FileTask().execute(intent);
		}
	};

	/* check screen on off */
	BroadcastReceiver screenOnOffReceiver = new BroadcastReceiver() {

		public final String ScreenOff = "android.intent.action.SCREEN_OFF";
		public final String ScreenOn = "android.intent.action.SCREEN_ON";

		@Override
		public void onReceive(Context context, Intent intent) {

			if (intent.getAction().equals(ScreenOff)) {

			} else if (intent.getAction().equals(ScreenOn)) {

			}
		}
	};

	BroadcastReceiver doConnectLongPollingReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			doConnectLongPolling();
		}
	};

	/* network status broadcast receiver */
	public static int CONNECTED_COUNT = 0;

	private final BroadcastReceiver mNetworkStateReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			// do specific task(s) based on the current network state, such
			// as enabling queuing of HTTP requests when currentNetworkInfo
			// is
			// connected etc.
			if (CONNECTED_COUNT == 0) {
				doConnectLongPolling();
			}
		}
	};

	private void doConnectLongPolling() {
		ConnectivityManager manager = (ConnectivityManager) mContext
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		if (Utils.checkNetwokState(manager)) {
			try {
				if (pollingThread.isAlive()) {
					pollingThread.cancel();
				}

				CONNECTED_COUNT = 1;
				pollingThread = new PollingThread((PollingService) mContext,
						mUiHandler);
				pollingThread.start();
				Log.i("connect-long", "pollingThread start");
			} catch (Exception e) {

			}
		} else {
			CONNECTED_COUNT = 0;
		}
	}
}
